<?php
/**
 * 
 * Ident Authority wrapper for wordpress
 * requires WP Passport plugin
 * 
 * @author Alton Crossley <crossleyframework@nogahidebootstrap.com>
 * @package Crossley Framework
 *  
 * @copyright Copyright (c) 2003-2009, Nogaide BootStrap INC. All rights reserved.
 * @license BSD http://opensource.org/licenses/bsd-license.php
 * @version $Id:$
 * 
 */

class X_User_Wordpress_Authority implements X_User_Id_Authority_Interface, X_User_Permission_Authority_Interface
{
    /**
     * path to the wordpress files from webroot
     */
    static public $sWpPath = 'blog/';
    
    /**
     * key in the session where wordpress user info is stored
     * @var unknown_type
     */
    static public $sSessionNamespace = 'wp-user';
    /**
     * mapping application permissions (key) to wordpress permissions (value)
     * @var array
     */
    protected $_aPermissionMap = array();
    
    /**
     * weather or not to forward via header or javascript(default)
     * @var boolean
     */
    protected $_bHeaderForward = false;
    /**
     * @return boolean
     */
    public function getHeaderForward ()
    {
        return $this->_bHeaderForward;
    }
    /**
     * @param boolean $_bHeaderForward
     */
    public function setHeaderForward ($bHeaderForward)
    {
        $this->_bHeaderForward = $bHeaderForward;
    }
    /**
     * verify session is started and start it if it is not
     * @return string Session Id
     */
    protected function _checkSession()
    {
        $sSessionId = session_id();
        if (empty($sSessionId) && session_start())
        {
            $sSessionId = session_id();
        }
        
        return $sSessionId;
    }
    
	/**
     * @param $sId
     */
    public function getUserIdData($sId)
    {
        throw new X_User_Exception(__METHOD__.' not implemented');
    }

	/**
     * @param $xId
     */
    public function varifyUid($xId)
    {
        throw new X_User_Exception(__METHOD__.' not implemented');
    }

	/**
     * @param $sToken
     */
    public function verifyToken($sToken)
    {
        throw new X_User_Exception(__METHOD__.' not implemented');
    }

	/**
     * @param $sUsername
     * @param $sPassword
     */
    public function verifyTokenPair($sUsername, $sPassword)
    {
        throw new X_User_Exception(__METHOD__.' not implemented');
    }
    /**
     * this method knows how to login the user (identify/authenticate)
     * ex. forward to a login page
     * 
     * @see X_User_Interface
     * @return String forward url
     */
    public function identify()
    {
        $sRedirectUrl = urlencode(X_Url::getCurrent());
        $sForwarUrl = '/'.self::$sWpPath.'wp-login.php?redirect_to='.$sRedirectUrl;
        if ($this->_bHeaderForward)
        {
            // no we dont send a status code, no known applicable
            header('Location: '.$sForwarUrl);
            exit(0);
        }
        
        return $sForwarUrl;
    }

	/**
     * @param $oUser
     */
    public function verifyUser(X_User_Interface $oUser, $bUseSession = true)
    {
        if ($bUseSession && $this->verifyUserSession($oUser)) return true;
        // @todo check the user data against other ways
        return false;
    }
    
	/**
     * @param $oUser
     */
    public function verifyUserSession(X_User_Interface $oUser)
    {
        $this->_checkSession();
        
        if (array_key_exists(self::$sSessionNamespace, $_SESSION))
        {
            // see if the user id matches the session id
            if (array_key_exists('id', $_SESSION[self::$sSessionNamespace]))
            {
                if ($oUser->getUid() == $_SESSION[self::$sSessionNamespace]['id'])
                {// todo be more rigerous about checking the session against the user: username displayname... etc.
                 return true;   
                }
                
                // the current user object is not set, or is a different user - set it to the right user
                $this->setIdentity($oUser);
                                             
                return true;
            }
            
        }
            
        // there is no valid session
        return false;
        
    }

	/**
     * check to see if the user is valid
     * right now subject and detail are combined like detail_subject
     * 
     * @param X_User_Interface $oUser
     * @param $sSubjectUri
     * @param $sDetail
     */
    public function isPermitted(X_User_Interface $oUser, $sSubjectUri, $sDetail = null)
    {        
        $this->_checkSession();
        
        if ($this->verifyUserSession($oUser))
        {
            $aCapabilities = &$_SESSION[self::$sSessionNamespace]['allcaps'];
            $sKey = $this->_buildPermKey($sSubjectUri, $sDetail);
            if (array_key_exists($sKey, $this->_aPermissionMap))
            {
                $sKey = $this->_aPermissionMap[$sKey];
            }
            
            if (array_key_exists($sKey, $aCapabilities)) 
            {
                return $aCapabilities[$sKey];                    
            }
            return false;
            
        }
        else
        {
            // user is bad or there is no session
            return false;
        }
    }
    
    /**
     * map application permissions to wordpress permissions using subject detail pairs
     * 
     * @param $sSubjectUri
     * @param $sDetail
     * @param $sWordpressCapability
     */
    public function addPermissionDetailMap($sSubjectUri, $sDetail, $sWordpressCapability)
    {
        $sKey = $this->_buildPermKey($sSubjectUri, $sDetail);
        $this->addPermissionMap($sKey, $sWordpressCapability);
    }
    
    /**
     * map application permissions to wordpress permissions
     * @param $sAlias
     * @param $sWordpressCapability
     * @return unknown_type
     */
    public function addPermissionMap($sAlias, $sWordpressCapability)
    {
        $this->_aPermissionMap[$sAlias] = $sWordpressCapability;        
    }
    /**
     * combined like detail_subject
     * 
     * @param string $sSubjectUri
     * @param string $sDetail
     * @return string
     */
    protected function _buildPermKey($sSubjectUri, $sDetail)
    {
    	if ($sSubjectUri == 'global')
        {
        	$sSubjectUri = null;
        }
        
        if (empty($sDetail))
        {
            return $sSubjectUri;
        }
        else if (empty($sSubjectUri))
        {
            return $sDetail;
        }
        else
        {
            $sKey = $sDetail . '_' . $sSubjectUri;
            return $sKey;
        }        
    }
	/**
	 * @param X_User_Interface $oUser
	 */
	public function setIdentity(X_User_Interface $oUser) 
	{
		
		if (array_key_exists(self::$sSessionNamespace, $_SESSION))
        {
            // see if the user id matches the session id
            if (array_key_exists('id', $_SESSION[self::$sSessionNamespace]))
            {
            	//$oUser->setData($_SESSION[self::$sSessionNamespace]);
            	
                // set the session info into the user overwriting the current user with the session
                $oUser->setUid($_SESSION[self::$sSessionNamespace]['id']);
                
                if (array_key_exists('user_login', $_SESSION[self::$sSessionNamespace]))
                    $oUser->setName($_SESSION[self::$sSessionNamespace]['user_login']);
                    
                if (array_key_exists('user_email', $_SESSION[self::$sSessionNamespace]))
                    $oUser->setEmail($_SESSION[self::$sSessionNamespace]['user_email']);
                    
                if (array_key_exists('user_nicename', $_SESSION[self::$sSessionNamespace]))
                    $oUser->setPrintableName($_SESSION[self::$sSessionNamespace]['user_nicename']);
                              
                return true;
            }
            
        }
	}

    
}